Code Choices (Exhibit 1)
To create this vortex, I wrote a function called make_petal() that places 150 petals in a circular pattern using trigonometry. I adjusted the inner and outer radius and the petal width, which allowed me to shape the form and density of the design. I used the “FantasticFox1” palette (I’m a big WA fan) and applied a mirrored gradient to give the piece a warm-to-cool symmetry. I also softened the borders with a faint black outline for a more smooth and delicate effect.
The animated version uses the same base pattern but rotates it over 500 frames, creating a slow, mesmerizing spin. I created the GIF using gifski_renderer() and embedded it into the document to keep the rendering process efficient.
Code
make_petal <- function (n_petals = 150 ,
inner_radius = 1 ,
outer_radius = 2.999 ,
width = 0.1 ) {
angles <- seq (0 , 2 * pi - (2 * pi / n_petals),
length.out = n_petals)
tibble (petal = 1 : n_petals, angle = angles) %>%
rowwise () %>%
mutate (
x = list (c (
0 ,
inner_radius * cos (angle - width),
outer_radius * cos (angle),
inner_radius * cos (angle + width)
)),
y = list (c (
0 ,
inner_radius * sin (angle - width),
outer_radius * sin (angle),
inner_radius * sin (angle + width)
)),
id = petal
) %>%
unnest (c (x, y)) %>%
ungroup () %>%
mutate (
gradient = abs (2 * (id - 1 ) / (n_petals - 1 ) - 1 )
)
}
# Create data
df <- make_petal (n_petals = 150 )
# Palette
fox_colors <- wes_palette ("FantasticFox1" )
mirror_palette <- colorRampPalette (fox_colors)(100 )
# Plot with faint borders
ggplot (df, aes (x, y, group = id, fill = gradient)) +
geom_polygon (color = rgb (0 , 0 , 0 , 0.05 ),
alpha = 0.95 ,
linejoin = "mitre" ,
size = 0.5 ) +
scale_fill_gradientn (colors = mirror_palette) +
coord_equal () +
theme_void () +
guides (fill = "none" ) +
ggtitle ("1. Spectral Event Horizon [Static]" ) +
theme (plot.title = element_text (size = 30 ,
hjust = 0.5 ,
face = "bold" )
)
Code
library (tidyverse)
library (wesanderson)
library (gganimate)
library (gifski)
# Petal data function with frame-based rotation
make_petal <- function (n_petals = 150 ,
frames = 60 ,
inner_radius = 1 ,
outer_radius = 2.999 ,
width = 0.1 ) {
angles <- seq (0 , 2 * pi - (2 * pi / n_petals), length.out = n_petals)
base <- tibble (petal = 1 : n_petals, angle = angles) %>%
rowwise () %>%
mutate (
x_base = list (c (
0 ,
inner_radius * cos (angle - width),
outer_radius * cos (angle),
inner_radius * cos (angle + width)
)),
y_base = list (c (
0 ,
inner_radius * sin (angle - width),
outer_radius * sin (angle),
inner_radius * sin (angle + width)
)),
id = petal
) %>%
unnest (c (x_base, y_base)) %>%
ungroup () %>%
mutate (
gradient = abs (2 * (id - 1 ) / (n_petals - 1 ) - 1 )
)
# Duplicate data across frames and rotate
expand_grid (base, frame = 1 : frames) %>%
mutate (
theta = 2 * pi * (frame - 1 ) / frames, # rotation per frame
x = x_base * cos (theta) - y_base * sin (theta),
y = x_base * sin (theta) + y_base * cos (theta)
)
}
df <- make_petal (n_petals = 100 , frames = 500 ) # fewer petals + frames
p <- ggplot (df, aes (x, y, group = interaction (id, frame), fill = gradient)) +
geom_polygon (color = rgb (0 , 0 , 0 , 0.05 ),
alpha = 0.95 ,
size = 0.3 ,
linejoin = "mitre" ) +
scale_fill_gradientn (colors = mirror_palette) +
coord_equal () +
theme_void () +
guides (fill = "none" ) +
ggtitle ("Spining" ) +
transition_manual (frame)
animation <- animate (
p,
fps = 25 ,
duration = 10 ,
width = 500 ,
height = 500 ,
res = 100 ,
renderer = gifski_renderer (),
verbose = TRUE
)
1. Spectral Event Horizon [GIF]
Code
knitr:: include_graphics ("vortex_spin_final.gif" )